class AudioAnalyser {
	private audioEle: HTMLAudioElement;
	private isStream: boolean = false;
	private audioContext: AudioContext = new AudioContext();
	private sourceNode: MediaStreamAudioSourceNode | MediaElementAudioSourceNode;
	private analyserNode: AnalyserNode;
	private dataArray: Uint8Array;
	private gainNode: GainNode;
	private stream: MediaStream | null;

	constructor(audioEle: HTMLAudioElement, isStream: boolean) {
		this.audioEle = audioEle;
		this.isStream = isStream;
		// 创建AudioContext对象
		if (this.isStream && this.audioEle.srcObject) {
			this.stream = this.audioEle.srcObject as MediaStream;
			this.sourceNode = this.audioContext.createMediaStreamSource(this.stream);
		} else {
			this.sourceNode = this.audioContext.createMediaElementSource(this.audioEle);
			this.stream = null;
		}
		this.analyserNode = this.audioContext.createAnalyser();
		this.analyserNode.fftSize = 32;
		// 将MediaElementAudioSourceNode对象连接到AnalyserNode对象
		this.sourceNode.connect(this.analyserNode);
		// 将AnalyserNode对象连接到AudioContext.destination
		this.analyserNode.connect(this.audioContext.destination);
		// 获取音频数据并计算音频级别
		this.dataArray = new Uint8Array(this.analyserNode.frequencyBinCount);
		this.gainNode = this.audioContext.createGain();
		this.sourceNode.connect(this.gainNode);
		this.gainNode.connect(this.audioContext.destination);

		// 音频增益 0.5
		this.gainNode.gain.value = 0.5;
	}

	public createAnalyser(onLevelChange: (level: number) => void) {
		const getAudioLevel = () => {
			window.requestAnimationFrame(getAudioLevel);
			this.analyserNode.getByteFrequencyData(this.dataArray);
			const average = this.dataArray.reduce((acc, curr) => acc + curr, 0) / this.dataArray.length;
			onLevelChange(average);
		};
		window.requestAnimationFrame(getAudioLevel);
	}

	// 切换扬声器
	public setSinkId = (id: string) => {
		// @ts-ignore
		this.audioContext.setSinkId(id);
	};

	// 设置麦克风声音大小
	public setStreamVol = (vol: number) => {
		const mute = () => {
			if (this.stream) {
				this.stream.getAudioTracks()[0].enabled = false;
			}
		};
		const unmute = () => {
			if (this.stream) {
				this.stream.getAudioTracks()[0].enabled = true;
			}
		};
		if (vol === 0) {
			mute();
		} else {
			unmute();
		}

		this.gainNode.gain.value = vol;
	};
}

export default AudioAnalyser;
